package com.yixing.tech.system.service.impl;

import com.yixing.tech.common.base.BaseMongoDao;
import com.yixing.tech.common.base.BusinessException;
import com.yixing.tech.common.base.Page;
import com.yixing.tech.common.base.PageRow;
import com.yixing.tech.common.enums.ErrCode;
import com.yixing.tech.common.enums.Status;
import com.yixing.tech.common.enums.YesOrNo;
import com.yixing.tech.system.dao.TenantDao;
import com.yixing.tech.system.po.Tenant;
import com.yixing.tech.system.service.ITenantService;
import com.yixing.tech.system.service.IUserService;
import com.yixing.tech.common.utils.DataUtil;
import com.yixing.tech.common.utils.WxApiUtil;
import com.yixing.tech.common.vo.s3.TenantVO;
import com.yixing.tech.common.vo.s3.UserVO;
import com.yixing.tech.common.vo.s3.WxPublicInfoVO;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author yixing tech
 * at 2021/12/20
 * describe：
 */
@Service
public class TenantServiceImpl implements ITenantService {

    @Resource
    private BaseMongoDao baseMongoDao;

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private TenantDao tenantDao;

    @Resource
    private IUserService userService;

    @Override
    public void add(TenantVO tenantVO) throws BusinessException {
        TenantVO condition = new TenantVO();
        condition.setName(tenantVO.getName());
        if (baseMongoDao.exists(condition, Tenant.class)) {
            throw new BusinessException(ErrCode.TENANT_EXISTED);
        }
        Tenant tenant = DataUtil.o2o(tenantVO, Tenant.class);
        tenant.setId(null);
        tenant.setClazz("company");
        tenant.setStatus(Status.def.ordinal());
        baseMongoDao.save(tenant);

    }

    @Override
    public void batchAdd(List<TenantVO> list) throws BusinessException {

    }

    @Override
    public TenantVO queryById(String id) {
        Tenant tenant = baseMongoDao.get(id, Tenant.class);
        return DataUtil.o2o(tenant, TenantVO.class);
    }

    @Override
    public List<TenantVO> queryByIds(List<String> ids) {
        return null;
    }

    @Override
    public TenantVO queryByCondition(TenantVO tenantVO) throws BusinessException {
        return null;
    }

    @Override
    public void update(TenantVO tenantVO) throws BusinessException {
        baseMongoDao.update(DataUtil.o2o(tenantVO, Tenant.class));
    }

    @Override
    public Page<TenantVO> list(PageRow<TenantVO> pageRow) {
        Criteria criteria = baseMongoDao.condition2Criteria(pageRow.getCondition());
        LookupOperation lookup = Aggregation.lookup("tenant", "children._id", "_id", "children");
        ProjectionOperation project = Aggregation.project("name", "status", "children", "type","code");
        SkipOperation skip = Aggregation.skip(Long.valueOf(pageRow.getPageNo() * pageRow.getPageSize()));
        LimitOperation limit = Aggregation.limit(pageRow.getPageSize());
        Aggregation agg = Aggregation.newAggregation(Aggregation.match(criteria), skip, limit, lookup, project);
        AggregationResults<TenantVO> results = mongoTemplate.aggregate(agg, "tenant", TenantVO.class);
        List<TenantVO> list = results.getMappedResults();

        long count = mongoTemplate.count(Query.query(criteria), Tenant.class);

        return new Page<>(list, pageRow.getPageSize(), pageRow.getPageNo() + 1, count);
    }

    @Override
    public List<TenantVO> list(TenantVO condition) {
        Criteria criteria = baseMongoDao.condition2Criteria(condition);
        ProjectionOperation project = Aggregation.project("name");
        Aggregation agg = Aggregation.newAggregation(Aggregation.match(criteria), project);
        AggregationResults<TenantVO> results = mongoTemplate.aggregate(agg, "tenant", TenantVO.class);
        List<TenantVO> list = results.getMappedResults();
        return list;
    }

    @Override
    public void deleteById(String id) throws BusinessException {
        Tenant tenant = new Tenant();
        tenant.setId(id);
        tenant.setIsDelete(YesOrNo.YES.ordinal());
        baseMongoDao.update(tenant);
    }

    @Override
    public void delete(List<String> ids) throws BusinessException {

    }

    @Override
    public void addChild(TenantVO vo) throws BusinessException {
        if (null == vo.getParentId()) throw new BusinessException(ErrCode.PARAMETER_ERROR);
        tenantDao.addChild(vo);
    }

    @Override
    public void freezeOrUnFreeze(String tenantId, boolean isFreeze) throws BusinessException {
        TenantVO tenant = new TenantVO();
        tenant.setId(tenantId);
        tenant.setStatus(isFreeze ? Status.freeze.ordinal() : Status.def.ordinal());
        update(tenant);
    }

    @Override
    public List<UserVO> getAdminList(String tenantId) {
        UserVO cond = new UserVO();
        cond.setTenantId(tenantId);
        cond.setIsAdmin(true);
        cond.setStatus(Status.def.ordinal());
        return userService.list(cond);
    }

    @Override
    public void syncWxPublicInfo(String tenantId) throws BusinessException {
        Tenant tenant = baseMongoDao.get(tenantId, Tenant.class);
        String token = WxApiUtil.getWxToken(tenant.getPublicAppId(), tenant.getPublicSecret());
        List<WxPublicInfoVO> list = WxApiUtil.getPublicUsers(token);
        mongoTemplate.remove(Query.query(Criteria.where("tenantId").is(tenantId)), "entity_634ffee1f296ec114c2e0c2f");
        list.forEach(m -> m.setTenantId(tenantId));
        mongoTemplate.insert(list, "entity_634ffee1f296ec114c2e0c2f");
    }

}
